//
//  AlfrescoWebScriptClient.m
//  Alfresco
//
//  Created by Michael Muller on 8/20/09.
//  Copyright 2010 Zia Consulting.  Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php 
//

#import "AlfrescoWebScriptClient.h"
#import "SBJsonParser.h"
#import "XMLParser.h"

@implementation AlfrescoWebScriptClient

@synthesize host;
@synthesize port;
@synthesize user;
@synthesize pass;
@synthesize ticket;

static AlfrescoWebScriptClient *singleton = nil;

+ (AlfrescoWebScriptClient *) instance {
    @synchronized(self)
    {
        if (singleton == nil) {
            singleton = [[AlfrescoWebScriptClient alloc] init];
		}
    }
    return singleton;
}

+ (void) cleanupForShutdown {
	if (singleton != nil) {
		[singleton release];
		singleton = nil;
	}
}

- (XMLNode *) callXMLWebScript:(NSString *)urlString {
	
	NSLog(@"calling web script at: %@", urlString);
	
	// create the parser obj
	NSURL *url = [[NSURL alloc] initWithString: urlString];
	XMLParser *parser = [[XMLParser alloc] initWithContentsOfURL: url];
	[url release];
	
	// parse the results
	[parser parse];
	XMLNode *rootNode = [[parser root] retain];
	[parser release];
	
	// log the structure
	NSMutableString *str = [[NSMutableString alloc] init];
	[rootNode dumpToString:str indent:0];
	NSLog(@"%@", str);
	[str release];

	return rootNode;
}

- (id)callJSONWebScript:(NSString *)url {
	
	NSLog(@"calling web script at: %@", url);
	
	NSURLRequest *theRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:url] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0];
	
	// send the request
    NSURLResponse *theResponse;
    NSError *theError;
	NSData *returnData = [NSURLConnection sendSynchronousRequest:theRequest returningResponse:&theResponse error:&theError];
	
	if (theError) {
		NSException *x = [NSException exceptionWithName:@"HTTP error calling web scipt" reason:[theError localizedDescription] userInfo:nil];
		@throw x;
	}
	
	// convert the response into an ascii string
	NSString* body = [[NSString alloc] initWithData:returnData encoding:NSASCIIStringEncoding];

	NSLog(@"response from web script: %@", body);
	
	// parse the JSON response into a hierarchy of dictionaries and arrays
    SBJsonParser *jsonParser = [SBJsonParser new];  
	id dict = [jsonParser objectWithString:body];  

	[body release];
	
	[jsonParser release];
	
	if (!dict) {
		NSException *x = [NSException exceptionWithName:@"JSONParseException" reason:@"failed to parse JSON response from Alfresco web script" userInfo:nil];
		@throw x;
	}

	if ([dict isKindOfClass: [NSDictionary class]]) {

		NSDictionary *status = [dict objectForKey:@"status"];
		NSString *message = [dict objectForKey:@"message"];
		NSString *server = [dict objectForKey:@"server"];
		NSString *time = [dict objectForKey:@"time"];
		
		bool responseIsErrorStruct = (status && message && server && time);
		
		// if the response has all these keys, we'll assume it's an error response
		if (responseIsErrorStruct) {
			NSException *x = [NSException exceptionWithName:@"WebScriptException" reason:message userInfo:dict];
			@throw x;
		}
	}
	
	return dict;
}

- (void)login {
	
	if (ticket) {
		return;
	}
	
	NSString *hostInURL = [self.host stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding];
	NSString *portInURL = [self.port stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding];
	NSString *userInURL = [self.user stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding];
	NSString *passInURL = [self.pass stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding];
	
    NSString *url = [[NSString alloc] initWithFormat:@"http://%@:%@/alfresco/service/api/login?u=%@&pw=%@&format=xml", hostInURL, portInURL, userInURL, passInURL];
	
	XMLNode *node = [self callXMLWebScript:url];

	NSLog(@"ticket: %@", node.body);
	
	self.ticket = node.body;
	
	static BOOL alreadyNotified = NO;
	if (!ticket && !alreadyNotified) {
		
		UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Offline Mode" message:@"Either the Internet is inaccessible, or invalid authentication information was provided." delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
		[alert show];
		
		alreadyNotified = YES;
	}
	[node release];
	[url release];
}

- (id)getSites {
	[self login];
	if (!ticket) {
		return nil;
	}
	NSString *url = [[NSString alloc] initWithFormat:@"http://%@:%@/alfresco/service/api/sites?alf_ticket=%@&format=json", self.host, self.port, self.ticket];
	id sites = [self callJSONWebScript:url];
	[url release];
	return sites;
}

- (XMLNode *)getChildrenOfNode:(NSString *)node {
	[self login];
	if (!ticket) {
		return nil;
	}
	NSString *url = [[NSString alloc] initWithFormat:@"http://%@:%@%@/children?alf_ticket=%@", self.host, self.port, node, self.ticket];
	XMLNode *response = [self callXMLWebScript:url];
	[url release];
	//NSLog(@"ref count: %@", [response retainCount]);
	return response;
}
 
- (XMLNode *) searchFor:(NSString *)pattern {
	[self login];
	if (!ticket) {
		return nil;
	}
	NSString *patternEncoded = [pattern stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding];
	NSString *url = [[NSString alloc] initWithFormat:@"http://%@:%@/alfresco/service/search/keyword.atom?q=%@&p=1&c=10&alf_ticket=%@", self.host, self.port, patternEncoded, self.ticket];
	XMLNode *response = [self callXMLWebScript:url];
	//[searchForEncoded release];
	//[url release];
	return response;
}

- (void)dealloc {
	[host release];
	[port release];
	[user release];
	[pass release];
	[ticket release];
	[super dealloc];
}

+ (NSString *) newStringWithNodeReferenceForGuid:(NSString *) guid {
	return [[NSString alloc] initWithFormat:@"/alfresco/service/api/node/workspace/SpacesStore/%@", guid];
}

@end


/*
 
 sample getchildren response:
 
 <entry>
 <author><name>pmahon</name></author>
 <content>54186503-ed0c-4037-98d4-d071fbe8368e</content>
 <id>urn:uuid:54186503-ed0c-4037-98d4-d071fbe8368e</id>
 <link rel="self" href="http://cm.ziaconsulting.com:80/alfresco/service/api/node/workspace/SpacesStore/54186503-ed0c-4037-98d4-d071fbe8368e"/>
 <link rel="edit" href="http://cm.ziaconsulting.com:80/alfresco/service/api/node/workspace/SpacesStore/54186503-ed0c-4037-98d4-d071fbe8368e"/>
 <link rel="cmis-allowableactions" href="http://cm.ziaconsulting.com:80/alfresco/service/api/node/workspace/SpacesStore/54186503-ed0c-4037-98d4-d071fbe8368e/permissions"/>
 <link rel="cmis-relationships" href="http://cm.ziaconsulting.com:80/alfresco/service/api/node/workspace/SpacesStore/54186503-ed0c-4037-98d4-d071fbe8368e/associations"/>
 <link rel="cmis-parent" href="http://cm.ziaconsulting.com:80/alfresco/service/api/node/workspace/SpacesStore/56ed3dfc-28e1-4c62-98df-0b52f7c94fe2"/>
 <link rel="cmis-folderparent" href="http://cm.ziaconsulting.com:80/alfresco/service/api/node/workspace/SpacesStore/54186503-ed0c-4037-98d4-d071fbe8368e/parent"/>
 <link rel="cmis-children" href="http://cm.ziaconsulting.com:80/alfresco/service/api/node/workspace/SpacesStore/54186503-ed0c-4037-98d4-d071fbe8368e/children"/>
 <link rel="cmis-descendants" href="http://cm.ziaconsulting.com:80/alfresco/service/api/node/workspace/SpacesStore/54186503-ed0c-4037-98d4-d071fbe8368e/descendants"/>
 <link rel="cmis-type" href="http://cm.ziaconsulting.com:80/alfresco/service/api/type/folder"/>
 <link rel="cmis-repository" href="http://cm.ziaconsulting.com:80/alfresco/service/api/repository"/>
 <published>2009-06-30T23:33:35.564Z</published>
 <summary></summary>
 <title>blog</title>
 <updated>2009-06-30T23:33:35.578Z</updated>
 <cmis:object>
 <cmis:properties>
 <cmis:propertyId cmis:name="ObjectId"><cmis:value>workspace://SpacesStore/54186503-ed0c-4037-98d4-d071fbe8368e</cmis:value></cmis:propertyId>
 <cmis:propertyString cmis:name="BaseType"><cmis:value>folder</cmis:value></cmis:propertyString>
 <cmis:propertyString cmis:name="ObjectTypeId"><cmis:value>folder</cmis:value></cmis:propertyString>
 <cmis:propertyString cmis:name="CreatedBy"><cmis:value>pmahon</cmis:value></cmis:propertyString>
 <cmis:propertyDateTime cmis:name="CreationDate"><cmis:value>2009-06-30T23:33:35.564Z</cmis:value></cmis:propertyDateTime>
 <cmis:propertyString cmis:name="LastModifiedBy"><cmis:value>pmahon</cmis:value></cmis:propertyString>
 <cmis:propertyDateTime cmis:name="LastModificationDate"><cmis:value>2009-06-30T23:33:35.578Z</cmis:value></cmis:propertyDateTime>
 <cmis:propertyString cmis:name="Name"><cmis:value>blog</cmis:value></cmis:propertyString>
 <cmis:propertyId cmis:name="ParentId"><cmis:value>workspace://SpacesStore/56ed3dfc-28e1-4c62-98df-0b52f7c94fe2</cmis:value></cmis:propertyId>
 </cmis:properties>
 </cmis:object>
 <cmis:terminator/>
 <app:edited>2009-06-30T23:33:35.578Z</app:edited>
 <alf:icon>http://cm.ziaconsulting.com:80/alfresco/images/icons/space-icon-default-16.gif</alf:icon>
 </entry>
 */

/*

 sample search response
 
 $ curl "http://cm.ziaconsulting.com/alfresco/service/search/keyword.atom?q=muller&p=1&c=10&alf_ticket=TICKET_31a20990ab70be90ad4fb15d34e8f6cf0c08a7b4"
 <?xml version="1.0" encoding="UTF-8"?>
 <feed xmlns="http://www.w3.org/2005/Atom" xmlns:opensearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:relevance="http://a9.com/-/opensearch/extensions/relevance/1.0/" xmlns:alf="http://www.alfresco.org/opensearch/1.0/">
 <generator version="3.2.0 (2039)">Alfresco (Community)</generator>
 <title>Alfresco Keyword Search: muller</title> 
 <updated>2009-10-03T04:12:52.441Z</updated>
 <icon>http://cm.ziaconsulting.com:80/alfresco/images/logo/AlfrescoLogo16.ico</icon>
 <author> 
 <name>mmuller</name>
 </author> 
 <id>urn:uuid:dbcc2489-7143-4c30-a481-4e574dac4e89</id>
 <opensearch:totalResults>5</opensearch:totalResults>
 <opensearch:startIndex>1</opensearch:startIndex>
 <opensearch:itemsPerPage>10</opensearch:itemsPerPage>
 <opensearch:Query role="request" searchTerms="muller" startPage="1" count="10" language="en-US"/>
 <link rel="alternate" href="http://cm.ziaconsulting.com:80/alfresco/service/search/keyword.atom?q=muller&amp;p=1&amp;c=10&amp;l=en-US&amp;guest=" type="text/html"/>
 <link rel="self" href="http://cm.ziaconsulting.com:80/alfresco/service/search/keyword.atom?q=muller&amp;p=1&amp;c=10&amp;l=en-US&amp;guest=" type="application/atom+xml"/>
 <link rel="search" type="application/opensearchdescription+xml" href="http://cm.ziaconsulting.com:80/alfresco/service/api/search/keyword/description.xml"/>
 <entry>
 <title>WBS-django-conversion.xls</title>
 <link rel="alternate" href="http://cm.ziaconsulting.com:80/alfresco/service/api/node/content/workspace/SpacesStore/986b162e-0867-4a7b-9f4f-0e3837cdc97b/WBS-django-conversion.xls"/>
 <icon>http://cm.ziaconsulting.com:80/alfresco/images/filetypes/xls.gif</icon>       
 <id>urn:uuid:986b162e-0867-4a7b-9f4f-0e3837cdc97b</id>
 <alf:noderef>workspace://SpacesStore/986b162e-0867-4a7b-9f4f-0e3837cdc97b</alf:noderef>
 <updated>2009-06-15T22:06:23.037Z</updated>
 <summary></summary>
 <author> 
 <name>mmahon</name>
 </author> 
 <relevance:score>0.012</relevance:score>
 </entry>
 
 */
